/*
 * Copyright 2012 Faculty of Informatics - Masaryk University.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cz.muni.fi.pa165.creatures.web;

import cz.muni.fi.pa165.creatures.dto.web.FunctionDTO;
import cz.muni.fi.pa165.creatures.dto.web.PersonDTO;
import cz.muni.fi.pa165.creatures.facades.PersonFunctionServiceFacade;
import cz.muni.fi.pa165.creatures.services.FunctionService;
import cz.muni.fi.pa165.creatures.services.PersonService;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.LocalizableMessage;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;

/**
 * ActionBean that handles the registration of new users.
 *
 * @author smikloso
 */
public class RegisterActionBean extends CreatureHuntingActionBean {

    private static final String ADMIN_USER_NAME = "admin";

    private static final String USER_NAME = "user";

    @SpringBean
    PersonService personService;

    @SpringBean
    FunctionService functionService;

    @SpringBean
    PersonFunctionServiceFacade personFunctionService;

    @ValidateNestedProperties({
        @Validate(field = "name", required = true,
            minlength = 5, maxlength = 20),
        @Validate(field = "password", required = true,
            minlength = 5, maxlength = 20)
    })
    private PersonDTO user;

    @Validate(required = true, minlength = 5,
            maxlength = 20, expression = "this == user.password")
    private String confirmPassword;

    /**
     * User we wants to register.
     * @return the user
     */
    public PersonDTO getUser() {
        return user;
    }

    /**
     * User we wants to register.
     * @param user user
     */
    public void setUser(PersonDTO user) {
        this.user = user;
    }

    /**
     * Confirmation password.
     * @return confirmed password
     */
    public String getConfirmPassword() {
        return confirmPassword;
    }

    /**
     * Confirmation password.
     * @param confirmPassword
     */
    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }

    @ValidationMethod
    public void validate(ValidationErrors errors) {
        if (personService.getByName(this.user.getName()) != null) {
            errors.add("user.name", new LocalizableError("username_taken"));
        }
        // if user to be registered has not chose its name as only
        // admin can have but it is the same after trimming and 
        // lower-casing, we do not permit it
        if (!this.user.getName().equals(ADMIN_USER_NAME)
             && user.getName().trim().toLowerCase().equals(ADMIN_USER_NAME)) {
            errors.add("user.name", new LocalizableError("username_not_allowed"));
        }
    }

    @DefaultHandler
    public Resolution register() {

        // if admin and use roles does not exist, create them,
        // they are the default ones which have to be in the system
        // everytime

        if (functionService.getByName(ADMIN_USER_NAME) == null) {
            functionService.create(new FunctionDTO(ADMIN_USER_NAME));
        }
        if (functionService.getByName(USER_NAME) == null) {
            functionService.create(new FunctionDTO(USER_NAME));
        }

        // create a new user
        Long user_id = personService.create(this.user);
        this.user.setId(Long.toString(user_id));

        // and decide if he is going to be added to the admin or user role
        if (this.user.getName().equals(ADMIN_USER_NAME)) {
            personFunctionService.addFunctionToPerson(
                    functionService.getByName(ADMIN_USER_NAME), user);
        } else {
            personFunctionService.addFunctionToPerson(
                    functionService.getByName(USER_NAME), user);
        }

        getContext().getMessages().add(
                new LocalizableMessage(getClass().getName() + ".successMessage",
                                       this.user.getName()));
        return new RedirectResolution("/login.jsp");
    }
}
